﻿//-----------------------------------------------------------------------
// <copyright file="Wpt.cs" company="MKCoolsoft">
//     Copyright (c) mkcoolsoft. All rights reserved.
// </copyright>
// <author>Mario Kuhl</author>
// <revision>26.01.2014 Initial version</revision>
//-----------------------------------------------------------------------

namespace MKCoolsoft.GPXLib
{
    #region usings

    using System;
    using System.Collections.Generic;
    using System.Xml.Serialization;

    #endregion usings

    /// <summary>
    /// <c>Wpt</c> represents a waypoint, point of interest, or named feature on a map.
    /// </summary>
    public class Wpt
    {
        #region private fields

        /// <summary>
        /// Elevation (in meters) of the point.
        /// </summary>
        private decimal eleField;

        /// <summary>
        /// The visibility flag for Elevation Field in then File.
        /// </summary>
        private bool eleSpecifiedField;

        /// <summary>
        /// Creation/modification timestamp for element. 
        /// Date and time in are in <c>Univeral</c> Coordinated Time (UTC), 
        /// not local time! Conforms to ISO 8601 specification for date/time representation. 
        /// Fractional seconds are allowed for millisecond timing in <c>tracklogs</c>.
        /// </summary>
        private DateTime timeField;

        /// <summary>
        /// The visibility flag for timeField in then File.
        /// </summary>
        private bool timeSpecifiedField;

        /// <summary>
        /// Magnetic variation (in degrees) at the point
        /// </summary>
        private decimal magvarField;

        /// <summary>
        /// The visibility flag for Magnetic variation in then File.
        /// </summary>
        private bool magvarSpecifiedField;

        /// <summary>
        /// Height (in meters) of geoid (mean sea level) above WGS84 earth ellipsoid. 
        /// As defined in NMEA GGA message.
        /// </summary>
        private decimal geoidheightField;

        /// <summary>
        /// The visibility flag for Height in then File.
        /// </summary>
        private bool geoidheightSpecifiedField;

        /// <summary>
        /// The GPS name of the waypoint. This field will be transferred to and from the GPS. 
        /// GPX does not place restrictions on the length of this field or the characters 
        /// contained in it. It is up to the receiving application to validate the field 
        /// before sending it to the GPS.
        /// </summary>
        private string nameField;

        /// <summary>
        /// GPS waypoint comment. Sent to GPS as comment.
        /// </summary>
        private string cmtField;

        /// <summary>
        /// A text description of the element. Holds additional information about the 
        /// element intended for the user, not the GPS.
        /// </summary>
        private string descField;

        /// <summary>
        /// Source of data. Included to give user some idea of reliability and accuracy of data. 
        /// "Garmin <c>eTrex</c>", "USGS quad Boston North", e.g.
        /// </summary>
        private string srcField;

        /// <summary>
        /// Link to additional information about the waypoint.
        /// </summary>
        private List<Link> linkListField;

        /// <summary>
        /// Text of GPS symbol name. For interchange with other programs, 
        /// use the exact spelling of the symbol as displayed on the GPS. 
        /// If the GPS abbreviates words, spell them out.
        /// </summary>
        private string symField;

        /// <summary>
        /// Type (classification) of the waypoint.
        /// </summary>
        private string typeField;

        /// <summary>
        /// Type of GPX fix.
        /// </summary>
        private Fix fixField;

        /// <summary>
        /// The visibility flag for fixField in then File.
        /// </summary>
        private bool fixSpecifiedField;

        /// <summary>
        /// Number of satellites used to calculate the GPX fix.
        /// </summary>
        private string satField;

        /// <summary>
        /// The Horizontal dilution of precision.
        /// </summary>
        private decimal hdopField;

        /// <summary>
        /// The visibility flag for Horizontal dilution in then File.
        /// </summary>
        private bool hdopSpecifiedField;

        /// <summary>
        /// Horizontal dilution of precision.
        /// </summary>
        private decimal vdopField;

        /// <summary>
        /// The visibility flag for Horizontal dilution in then File.
        /// </summary>
        private bool vdopSpecifiedField;

        /// <summary>
        /// Position dilution of precision.
        /// </summary>
        private decimal pdopField;

        /// <summary>
        /// The visibility flag for Position dilution in then File.
        /// </summary>
        private bool pdopSpecifiedField;

        /// <summary>
        /// Number of seconds since last DGPS update.
        /// </summary>
        private decimal ageofdgpsdataField;

        /// <summary>
        /// The visibility flag for Number of seconds in then File.
        /// </summary>
        private bool ageofdgpsdataSpecifiedField;

        /// <summary>
        /// ID of DGPS station used in differential correction.
        /// </summary>
        private string dgpsidField;

        /// <summary>
        /// You can add extend GPX by adding your own elements from another schema here.
        /// </summary>
        private Extensions extensionsField;

        /// <summary>
        /// The latitude of the point. This is always in decimal degrees, 
        /// and always in WGS84 datum.
        /// </summary>
        private decimal latField;

        /// <summary>
        /// The longitude of the point. This is always in decimal degrees, 
        /// and always in WGS84 datum.
        /// </summary>
        private decimal lonField;

        #endregion private fields

        #region constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="Wpt"/> class.
        /// </summary>
        public Wpt()
        {
            this.extensionsField = new Extensions();
            this.linkListField = new List<Link>();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Wpt"/> class.
        /// </summary>
        /// <param name="lat">Latitude of waypoint</param>
        /// <param name="lon">Longitude of waypoint</param>
        public Wpt(decimal lat, decimal lon)
        {
            this.latField = lat;
            this.lonField = lon;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Wpt"/> class.
        /// This "private" constructor is for hiding the public constructor for 
        /// serialize / deserialize
        /// </summary>
        /// <param name="dummy">Dummy parameter</param>
        private Wpt(int dummy) 
        {
        }

        #endregion constructors

        #region public properties

        /// <summary>
        /// Gets or sets Elevation (in meters) of the point.
        /// </summary>
        [XmlElementAttribute("ele")]
        public decimal Ele
        {
            get
            {
                return this.eleField;
            }

            set
            {
                this.eleField = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the Elevation is enabled.
        /// </summary>
        [XmlIgnoreAttribute]
        public bool EleSpecified
        {
            get
            {
                return this.eleSpecifiedField;
            }

            set
            {
                this.eleSpecifiedField = value;
            }
        }

        /// <summary>
        /// Gets or sets the timestamp.
        /// </summary>
         [XmlElementAttribute("time")]
        public DateTime Time
        {
            get
            {
                return this.timeField;
            }

            set
            {
                this.timeField = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the Time is enabled.
        /// </summary>
        [XmlIgnoreAttribute]
        public bool TimeSpecified
        {
            get
            {
                return this.timeSpecifiedField;
            }

            set
            {
                this.timeSpecifiedField = value;
            }
        }

        /// <summary>
        /// Gets or sets the Magnetic variation (in degrees) at the point
        /// </summary>
        public decimal Magvar
        {
            get
            {
                return this.magvarField;
            }

            set
            {
                this.magvarField = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the Magnetic variation is enabled.
        /// </summary>
        [XmlIgnoreAttribute]
        public bool MagvarSpecified
        {
            get
            {
                return this.magvarSpecifiedField;
            }

            set
            {
                this.magvarSpecifiedField = value;
            }
        }

        /// <summary>
        /// Gets or sets the Height
        /// </summary>
        public decimal Geoidheight
        {
            get
            {
                return this.geoidheightField;
            }

            set
            {
                this.geoidheightField = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the Height is enabled.
        /// </summary>
        [XmlIgnoreAttribute]
        public bool GeoidheightSpecified
        {
            get
            {
                return this.geoidheightSpecifiedField;
            }

            set
            {
                this.geoidheightSpecifiedField = value;
            }
        }

        /// <summary>
        /// Gets or sets the Name of the waypoint.
        /// </summary>
        [XmlElementAttribute("name")]
        public string Name
        {
            get
            {
                return this.nameField;
            }

            set
            {
                this.nameField = value;
            }
        }

        /// <summary>
        /// Gets or sets the comment of a waypoint.
        /// </summary>
        public string Cmt
        {
            get
            {
                return this.cmtField;
            }

            set
            {
                this.cmtField = value;
            }
        }

        /// <summary>
        /// Gets or sets the Description of a waypoint.
        /// </summary>
        public string Desc
        {
            get
            {
                return this.descField;
            }

            set
            {
                this.descField = value;
            }
        }

        /// <summary>
        /// Gets or sets "Source of data" for a waypoint
        /// </summary>
        public string Src
        {
            get
            {
                return this.srcField;
            }

            set
            {
                this.srcField = value;
            }
        }

        /// <summary>
        /// Gets or sets the LinkList.
        /// </summary>
        [XmlElementAttribute("link")]
        public List<Link> LinkList
        {
            get
            {
                return this.linkListField;
            }

            set
            {
                this.linkListField = value;
            }
        }

        /// <summary>
        /// Gets or sets the Symbol name
        /// </summary>
        public string Sym
        {
            get
            {
                return this.symField;
            }

            set
            {
                this.symField = value;
            }
        }

        /// <summary>
        /// Gets or sets the Type (classification) of a waypoint
        /// </summary>
        public string Type
        {
            get
            {
                return this.typeField;
            }

            set
            {
                this.typeField = value;
            }
        }

        /// <summary>
        /// Gets or sets the Fix.
        /// </summary>
        public Fix Fix
        {
            get
            {
                return this.fixField;
            }

            set
            {
                this.fixField = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the Fix is enabled.
        /// </summary>
        [XmlIgnoreAttribute]
        public bool FixSpecified
        {
            get
            {
                return this.fixSpecifiedField;
            }

            set
            {
                this.fixSpecifiedField = value;
            }
        }

        /// <summary>
        /// Gets or sets the number of satellites.
        /// </summary>
        [XmlElementAttribute(DataType = "nonNegativeInteger")]
        public string Sat
        {
            get
            {
                return this.satField;
            }

            set
            {
                this.satField = value;
            }
        }

        /// <summary>
        /// Gets or sets the Horizontal dilution of precision.
        /// </summary>
        public decimal Hdop
        {
            get
            {
                return this.hdopField;
            }

            set
            {
                this.hdopField = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the Horizontal dilution is enabled.
        /// </summary>
        [XmlIgnoreAttribute]
        public bool HdopSpecified
        {
            get
            {
                return this.hdopSpecifiedField;
            }

            set
            {
                this.hdopSpecifiedField = value;
            }
        }

        /// <summary>
        /// Gets or sets Vertical dilution of precision.
        /// </summary>
        public decimal Vdop
        {
            get
            {
                return this.vdopField;
            }

            set
            {
                this.vdopField = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the Vertical dilution is enabled.
        /// </summary>
        [XmlIgnoreAttribute]
        public bool VdopSpecified
        {
            get
            {
                return this.vdopSpecifiedField;
            }

            set
            {
                this.vdopSpecifiedField = value;
            }
        }

        /// <summary>
        /// Gets or sets the Position dilution of precision.
        /// </summary>
        public decimal Pdop
        {
            get
            {
                return this.pdopField;
            }

            set
            {
                this.pdopField = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the Position dilution is enabled.
        /// </summary>
        [XmlIgnoreAttribute]
        public bool PdopSpecified
        {
            get
            {
                return this.pdopSpecifiedField;
            }

            set
            {
                this.pdopSpecifiedField = value;
            }
        }

        /// <summary>
        /// Gets or sets the Number of seconds since last DGPS update.
        /// </summary>
        public decimal Ageofdgpsdata
        {
            get
            {
                return this.ageofdgpsdataField;
            }

            set
            {
                this.ageofdgpsdataField = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the Number of seconds is enabled.
        /// </summary>
        [XmlIgnoreAttribute]
        public bool AgeofdgpsdataSpecified
        {
            get
            {
                return this.ageofdgpsdataSpecifiedField;
            }

            set
            {
                this.ageofdgpsdataSpecifiedField = value;
            }
        }

        /// <summary>
        /// Gets or sets the ID of DGPS station used in differential correction.
        /// </summary>
        [XmlElementAttribute(DataType = "integer")]
        public string Dgpsid
        {
            get
            {
                return this.dgpsidField;
            }

            set
            {
                this.dgpsidField = value;
            }
        }

        /// <summary>
        /// Gets or sets the Extensions
        /// </summary>
        public Extensions Extensions
        {
            get
            {
                return this.extensionsField;
            }

            set
            {
                this.extensionsField = value;
            }
        }

        /// <summary>
        /// Gets or sets the Latitude of a waypoint
        /// </summary>
        [XmlAttributeAttribute("lat")]
        public decimal Lat
        {
            get
            {
                return this.latField;
            }

            set
            {
                this.latField = value;
            }
        }

        /// <summary>
        /// Gets or sets the Longitude of a waypoint
        /// </summary>
        [XmlAttributeAttribute("lon")]
        public decimal Lon
        {
            get
            {
                return this.lonField;
            }

            set
            {
                this.lonField = value;
            }
        }

        #endregion public properties
    }
}
